package edu.neu.cloud_factory.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.neu.cloud_factory.entity.po.*;
import edu.neu.cloud_factory.entity.vo.DeviceVo;
import edu.neu.cloud_factory.service.*;
import edu.neu.cloud_factory.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 设备 前端控制器
 * </p>
 *
 * @author halozhy
 * @since 2021-07-15
 */
@RestController
@RequestMapping("/api/device")
public class DeviceController {
    @Autowired
    DeviceService deviceService;

    @Autowired
    DeviceTypeService deviceTypeService;

    @Autowired
    UserService userService;

    @Autowired
    ScheduleService scheduleService;

    @Autowired
    FactoryService factoryService;

    @Autowired
    RentRecService rentRecService;

    @Autowired
    OrderService orderService;

    @Autowired
    DeviceCapacityService deviceCapacityService;

    @GetMapping("/list_all")
    public List<DeviceVo> list() {
        // TODO 鉴权
        List<DeviceType> deviceTypeList = deviceTypeService.list();

        List<Device> deviceList = deviceService.list();
        List<DeviceVo> deviceVoList = new ArrayList<>();
        deviceList.forEach(device -> {
            DeviceVo deviceVo = new DeviceVo();
            deviceVo.setId(device.getDId());
            deviceVo.setName(device.getDName());
            deviceVo.setSpec(device.getDSpec());
            deviceVo.setDescribe(device.getDDescribe());
            deviceVo.setType_id(device.getDTypeId());
            for (DeviceType pt :
                    deviceTypeList) {
                if (pt.getDtId().equals(device.getDTypeId())) {
                    deviceVo.setType_name(pt.getDtName());
                    break;
                }
            }
            deviceVoList.add(deviceVo);
        });
        return deviceVoList;
    }

    @PostMapping("/list")
    public JSONObject list(@RequestBody String CONTENT) {
        JSONObject j = JSONObject.parseObject(CONTENT);
        // TODO 鉴权
        return deviceService.listDevice(
                j.getInteger("page"),
                j.getInteger("limit"),
                j.getString("id"),
                j.getString("name"),
                j.getString("describe")
        );
    }

    @PostMapping("/list_fac")
    public JSONObject listFac(@RequestBody String CONTENT) {
        JSONObject j = JSONObject.parseObject(CONTENT);
        // TODO 鉴权
        return deviceService.listDeviceFac(
                j.getInteger("page"),
                j.getInteger("limit"),
                j.getString("id"),
                j.getString("name"),
                j.getString("describe"),
                j.getString("user_id")
        );
    }

    @PostMapping("/add")
    public int add(@RequestBody String CONTENT) {
        // TODO 优化鉴权
        JSONObject j = JSONObject.parseObject(CONTENT);
        if (!Utils.checkEmpty(j, Arrays.asList("name", "type_id", "dept_name", "user_id"))) {
            return -2; // 存在空字段
        }
        Device device = new Device();
        device.setDName(j.getString("name"));
        device.setDSpec(j.getString("spec"));
        device.setDDescribe(j.getString("describe"));
        device.setDRentRecId(null); // 设备创建时肯定未租用
        device.setDState("闲置"); // 设备创建时状态为闲置
        long typeId = j.getLong("type_id");
        if (deviceTypeService.getById(typeId) == null) {
            return -1; // 设备类型id错误
        }
        device.setDTypeId(typeId);
        User u = userService.getById(j.getLong("user_id"));
        if (u == null) {
            return -3; // 用户id不正确
        }
        String dept_name = j.getString("dept_name");
        if (dept_name.equals("自有")) {
            // 验证传入的user_id必须为云工厂管理员
            if (u.getUType().equals("云工厂管理员")) {
                device.setDDeptName(dept_name);
                device.setDFactoryId(u.getUFactoryId());
                deviceService.save(device);
                return 0;
            } else {
                return -4; // 权限错误
            }
        } else if (dept_name.equals("中心")) {
            // 验证传入的user_id必须为超级管理员
            if (u.getUType().equals("超级管理员")) {
                device.setDDeptName(dept_name);
                device.setDFactoryId(null);
                deviceService.save(device);
                return 0;
            } else {
                return -4; // 权限错误
            }
        } else {
            return -4;
        }
    }

    @GetMapping("/can_update")
    public int canUpdate(int dId) {
        Device device = deviceService.getById(dId);
        if (device != null) {
            if (device.getDRentRecId() != null) {
                return -1; // 被租用
            }
            if (device.getDState().equals("开机")) {
                return -2; // 生产中
            }
            return 0;
        }
        return -3; // 找不到
    }


    @PostMapping("/update")
    public int update(@RequestBody String CONTENT) {
        // TODO 优化鉴权
        JSONObject j = JSONObject.parseObject(CONTENT);
        if (!Utils.checkEmpty(j, Arrays.asList("id", "name", "type_id", "user_id"))) {
            return -2; // 存在空字段
        }
        User u = userService.getById(j.getLong("user_id"));
        if (u == null) {
            return -6; // 用户id不存在
        }
        Device device = deviceService.getById(j.getInteger("id"));
        if (device == null) {
            return -1; // 无此设备
        }
        device.setDName(j.getString("name"));
        device.setDSpec(j.getString("spec"));
        device.setDDescribe(j.getString("describe"));
        long typeId = j.getLong("type_id");
        if (deviceTypeService.getById(typeId) == null) {
            return -3; // 设备类型id错误
        }
        device.setDTypeId(j.getLong("type_id"));
        if (device.getDRentRecId() != null) {
            return -4; // 设备被租用，无法修改
        }

        // 通过设备状态了解设备是否能被修改
        if (device.getDState().equals("开机")) {
            return -5; // 设备仍在开机生产中，无法修改
        }

        // 以下为直接检索排产计划的来判断的方法
        // 检索出排产计划里面设备编号为此设备，且 开始时间<= 现在 && 现在<= 结束时间 的计划
        // 如果计划数量不为0，则认为设备仍在生产中，无法修改
//        Calendar calendar = Calendar.getInstance();
//        calendar.getTime();
////        Date date = new Date();
//        List<Schedule> scheduleList = scheduleService.selectStartingScheduleListByDIdAndTime(device.getDId(), calendar.getTime());
//        if (scheduleList.size() != 0) {
//            return -5; // 设备仍在生产中，无法修改
//        }

        if (!u.getUType().equals("超级管理员") && !device.getDFactoryId().equals(u.getUFactoryId()) ) {
            // 不是超级管理员 且 自己的工厂id不等于设备所属的工厂id
            return -6; // 权限错误
        }
        deviceService.updateById(device);
        return 0;
    }

    @GetMapping("/delete")
    public int delete(int dId) {
        // TODO 鉴权
        Device device = deviceService.getById(dId);
        if (device == null) {
            return -2; // 无此设备
        }
        if (device.getDState().equals("开机")) {
            return -1; // 设备仍在开机生产中，无法删除
        }
        if (device.getDRentRecId() != null) {
            return -3; // 设备被租用，无法删除
        }
        deviceService.removeById(device);
        return 0;
    }

    /**
     * 关闭设备
     *
     * @param CONTENT
     * @return 0 ok -1 无此设备 -2 此设备已经关机 -3 有排产计划，不允许关机
     */
    @PostMapping("/shutdown")
    public int shutdown(@RequestBody String CONTENT) {
        // TODO 鉴权
        JSONObject j = JSONObject.parseObject(CONTENT);
        return deviceService.shutdown(j.getInteger("id"));
    }

    /**
     * 开机设备
     *
     * @param CONTENT
     * @return 0 ok -1 无此设备 -2 此设备已经是闲置状态
     */
    @PostMapping("/open")
    public int open(@RequestBody String CONTENT) {
        // TODO 鉴权
        JSONObject j = JSONObject.parseObject(CONTENT);
        return deviceService.open(j.getInteger("id"));
    }

    @GetMapping("list_rentable")
    public List<DeviceVo> listRentable() {
        // 暂且无需鉴权
        List<Device> deviceList = deviceService.list();
        List<DeviceType> deviceTypeList = deviceTypeService.list();
        List<DeviceVo> deviceVoList = new ArrayList<>();
        deviceList.forEach(device -> {
            // 只能租用产能中心未被租用且无故障的设备信息
            if (device.getDDeptName().equals("中心")
                    && device.getDRentRecId() == null
                    && !device.getDState().equals("故障")
                    && !device.getDState().equals("开机")) {
                DeviceVo deviceVo = new DeviceVo();
                deviceVo.setId(device.getDId());
                deviceVo.setName(device.getDName());
                deviceVo.setSpec(device.getDSpec());
                deviceVo.setDescribe(device.getDDescribe());
                deviceVo.setType_id(device.getDTypeId());
                for (DeviceType pt :
                        deviceTypeList) {
                    if (pt.getDtId().equals(device.getDTypeId())) {
                        deviceVo.setType_name(pt.getDtName());
                        break;
                    }
                }
                deviceVoList.add(deviceVo);
            }
        });
        return deviceVoList;
    }

    @PostMapping("rent_device")
    public int rent_device(@RequestBody String CONTENT) {
        JSONObject j = JSONObject.parseObject(CONTENT);
        if (Utils.checkEmpty(j, Arrays.asList("user_id", "device_id", "expire_time"))) {
            // 1.用户是否为云工厂管理员 2.用户所处的工厂状态正常 3. 只能租用产能中心未被租用且无故障的设备信息
            User u = userService.getById(j.getLong("user_id"));
            if (u == null) {
                return -1;
            }
            if (!u.getUType().equals("云工厂管理员")) {
                return -2;
            }
            Factory factory = factoryService.getById(u.getUFactoryId());
            if (factory == null) {
                return -3;
            }
            if (!factory.getFState().equals("正常")) {
                return -4;
            }
            Device device = deviceService.getById(j.getLong("device_id"));
            if (device == null) {
                return -5;
            }
            if (device.getDDeptName().equals("中心")
                    && device.getDRentRecId() == null
                    && !device.getDState().equals("故障")
                    && !device.getDState().equals("开机")) {
                // 可以租用
                // 首先创建 并 保存租用记录
                RentRec rentRec = new RentRec();
                LocalDateTime rt = LocalDateTime.now();
                rentRec.setRRentTime(rt);
                rentRec.setRExpireTime(Utils.parseToLocalDateTime(j.getString("expire_time")));
                rentRec.setRFactoryId(factory.getFId());
                rentRec.setRDeviceId(device.getDId());
                rentRecService.save(rentRec);
                // 然后更新此设备的租用记录id
                device.setDRentRecId(rentRec.getRId());
                deviceService.updateById(device);
                return 0;
            } else {
                return -6;
            }
        } else {
            return -2;
        }

    }

    @PostMapping("dis_rent_device")
    public int dis_rent_device(@RequestBody String CONTENT) {
        JSONObject j = JSONObject.parseObject(CONTENT);
        if (Utils.checkEmpty(j, Arrays.asList("user_id", "device_id"))) {
            // 1.用户是否为云工厂管理员 2. 只能归还产能中心已被租用 且 不为生产状态 的设备
            User u = userService.getById(j.getLong("user_id"));
            if (u == null) {
                return -1;
            }
            if (!u.getUType().equals("云工厂管理员")) {
                return -2;
            }
            Factory factory = factoryService.getById(u.getUFactoryId());
            if (factory == null) {
                return -3;
            }
            Device device = deviceService.getById(j.getLong("device_id"));
            if (device == null) {
                return -5;
            }
            if (device.getDState().equals("开机")) {
                return -7; // 设备仍在生产中
            }
            if (device.getDDeptName().equals("中心")
                    && device.getDRentRecId() != null
            ) {
                // 可以归还
                // 首先修改 并 保存 租用记录的归还时间
                RentRec rentRec = rentRecService.getById(device.getDRentRecId());
                LocalDateTime rt = LocalDateTime.now();
                rentRec.setRRecycleTime(rt);
                rentRecService.updateById(rentRec);
                // 然后更新此设备的租用记录id为null
                device.setDRentRecId(null);
                deviceService.updateById(device);
                return 0;
            } else {
                return -6;
            }
        } else {
            return -2;
        }
    }

    @PostMapping("recycle_device")
    public int recycle_device(@RequestBody String CONTENT) {
        JSONObject j = JSONObject.parseObject(CONTENT);
        if (Utils.checkEmpty(j, Arrays.asList("user_id", "device_id"))) {
            // 1.用户是否为超级管理员 2. 设备必须到期才能收回 3. 设备不为生产状态
            User u = userService.getById(j.getLong("user_id"));
            if (u == null) {
                return -1;
            }
            if (!u.getUType().equals("超级管理员")) {
                return -3;
            }
            Device device = deviceService.getById(j.getLong("device_id"));
            if (device == null) {
                return -4;
            }
            if (device.getDState().equals("开机")) {
                return -5; // 设备仍在生产中
            }
            if (device.getDDeptName().equals("中心")
                    && device.getDRentRecId() != null
            ) {
                // 查出记录，是否已经到期
                RentRec rentRec = rentRecService.getById(device.getDRentRecId());
                LocalDateTime rt = LocalDateTime.now();
                if (rt.isAfter(rentRec.getRExpireTime())) {
                    // 到期，可以收回
                    rentRec.setRRecycleTime(rt);
                    rentRecService.updateById(rentRec);
                    // 然后更新此设备的租用记录id为null
                    device.setDRentRecId(null);
                    deviceService.updateById(device);
                    return 0;
                } else {
                    return -6; // 设备未到期
                }
            } else {
                return -7;
            }
        } else {
            return -2;
        }
    }

    @GetMapping("/list_suit")
    public List<DeviceVo> listSuit(String userId, String orderId) {
        // 设备来源必须是自己工厂下的
        User u = userService.getById(Long.parseLong(userId));

        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(i -> i.eq("r_factory_id", u.getUFactoryId())
                .or().eq("d_factory_id", u.getUFactoryId()));

        List<Device> deviceList = deviceService.listJoinRentRec(queryWrapper);
        Map<Long, Device> deviceMap = new HashMap<>();
        deviceList.forEach(device -> {
            deviceMap.put(device.getDId(), device);
        });

        // 而且产能配置有这个产品的产能信息
        // 1. 通过订单查产品
        Order order = orderService.getById(Long.parseLong(orderId));
        if (order == null) {
            return null;
        }
        // 2. 通过产品查产能
        QueryWrapper<DeviceCapacity> deviceCapacityQueryWrapper = new QueryWrapper<>();
        deviceCapacityQueryWrapper.eq("c_product_id", order.getOProductId());
        List<DeviceCapacity> deviceCapacityList = deviceCapacityService.list(deviceCapacityQueryWrapper);
        // 3. 取这些产能中device_id和device_list中id一致的，返回
        List<DeviceVo> result = new ArrayList<>();
        deviceCapacityList.forEach(deviceCapacity -> {
            Device d = deviceMap.get(deviceCapacity.getCDeviceId());
            if (d != null) {
                DeviceVo deviceVo = new DeviceVo();
                deviceVo.setName(d.getDName());
                deviceVo.setId(d.getDId());
                result.add(deviceVo);
            }
        });
        return result;
    }
}

